/**
 * @author haixuanwo
 * @email haixuanwo_clark@hotmail.com
 * @date 2021-03-25
 * @brief 用户管理类
 */

#include "userManager.h"
#include <iostream>

#define CREATE_USER_TABLE "CREATE TABLE USER(" \
                          "NAME           TEXT    NOT NULL," \
                          "PASSWD         TEXT    NOT NULL," \
                          "ADMINI         INT     NOT NULL);"

#define SELECT_ALL_USER "SELECT * from USER"

// SELECT name FROM sqlite_master WHERE type='table' AND name='{table_name}';
// SELECT name FROM sqlite_master WHERE type='table' AND name='table_name';
// SELECT count(*) FROM sqlite_master WHERE type='table' AND name='{table_name}';
#define SELECT_USER_TABLE "SELECT count(*) FROM sqlite_master WHERE type='table' AND name='USER';"

UserManager::UserManager()
{
    v_user = new std::vector<User_t>;
    userDB = new mySqlite(STUDENT_MANAGE_SYSTEM);

    int tableCount = 0;
    if (userDB->exec_sql_cmd(SELECT_USER_TABLE, &tableCount))
    {
        if (0 < tableCount)
        {
            // 获取数据库中用户数据
            get_all_user();
            show_all_user();
        }
        else
        {
            // 创建用户表
            if(userDB->exec_sql_cmd(CREATE_USER_TABLE))
                std::cout<<"create table user successful"<<std::endl;
            else
                std::cout<<"create table user fail"<<std::endl;
        }
    }
}

bool UserManager::add_user(std::string &name, std::string &passwd, int administrator)
{
    User_t user;

    if (match_user(name))
    {
        std::cout<<"the users already exist, add fail"<<std::endl;
        return false;
    }

    user.name = name;
    user.passwd = passwd;
    user.administrator = administrator;
    v_user->push_back(user);

    char cmd[1024] = {0};
    snprintf(cmd, sizeof(cmd),
        "INSERT INTO USER (NAME,PASSWD,ADMINI) VALUES ('%s', '%s', %d);",
        name.c_str(), passwd.c_str(), administrator);

    if (userDB->exec_sql_cmd(cmd))
    {
        std::cout<<"add user successful!name:"<<name<<" passwd:"<<passwd<<" administrator:"<<administrator<<std::endl;
        show_all_user();
        return true;
    }
    else
        std::cout<<"add user fail"<<std::endl;
    return false;
}

bool UserManager::delete_user(std::string &name)
{
    char sqlCmd[1024] = {0};

    for (auto it = v_user->begin(); it != v_user->end(); ++it)
    {
        if (0 == it->name.compare(name))
        {
            // snprintf(sqlCmd, sizeof(sqlCmd),  "DELETE from USER where NAME IS '%s';", name.c_str());
            snprintf(sqlCmd, sizeof(sqlCmd),  "DELETE from USER where NAME='%s';", name.c_str());

            if (userDB->exec_sql_cmd(sqlCmd))
            {
                std::cout<<"del user successful! name:"<<name<<std::endl;
                v_user->erase(it);
                show_all_user();
                return true;
            }

            std::cout<<"delete user fail:"<<name<<std::endl;
        }
    }
    return false;
}

bool UserManager::select_user(std::string &name)
{
    User_t user;
    if (match_user(name, nullptr, &user))
    {
        std::cout<<"select successful user name:"<<user.name<<" passwd:"<<user.passwd<<" administrator:"<<user.administrator<<std::endl;
        return true;
    }
    else
    {
        std::cout<<"select fail, have no "<<name<<std::endl;
        return false;
    }
}

bool UserManager::change_user(std::string &name, std::string &passwd, int administrator)
{
    char sqlCmd[1024] = {0};

    for (auto it = v_user->begin(); it != v_user->end(); ++it)
    {
        if (0 == it->name.compare(name))
        {
            snprintf(sqlCmd, sizeof(sqlCmd),
                "UPDATE USER set PASSWD='%s', ADMINI=%d where NAME='%s'; ",
                passwd.c_str(), administrator, name.c_str());

            if (userDB->exec_sql_cmd(sqlCmd))
            {
                std::cout<<"update user successful! name:"<<name<<" passed:"<<passwd<<" administrator:"<<administrator<<std::endl;
                it->passwd = passwd;
                it->administrator = administrator;
                show_all_user();
                return true;
            }
        }
    }

    std::cout<<"change fail: "<<name<<std::endl;
    return false;
}

bool UserManager::match_user(std::string &name, std::string *passwd, User_t *matchedUser)
{
    for (auto user:*v_user)
    {
        // 匹配name
        if (0 == user.name.compare(name))
        {
            // 匹配passwd
            if (nullptr != passwd && 0 != user.passwd.compare(*passwd))
            {
                continue;
            }

            // 获取匹配的user
            if (nullptr != matchedUser)
            {
                *matchedUser = user;
            }
            return true;
        }
    }
    return false;
}

// 从数据库中获取所有用户数据
bool UserManager::get_all_user()
{
    std::string tableData;

    if (userDB->sql_select(SELECT_ALL_USER, tableData))
    {
        // 初始化v_user容器
        User_t user;
        auto pos = 0;

        pos = tableData.find_first_of(';');
        tableData.erase(0, pos+1);  // 删除第一行的元素名称

        while (tableData.size())
        {
            pos = tableData.find_first_of(',');
            user.name = tableData.substr(0, pos);
            tableData.erase(0, pos+1);

            pos = tableData.find_first_of(',');
            user.passwd = tableData.substr(0, pos);
            tableData.erase(0, pos+1);

            pos = tableData.find_first_of(';');
            user.administrator = atoi(tableData.substr(0, pos).c_str());
            tableData.erase(0, pos+1);

            v_user->push_back(user);
        }
        return true;
    }
    return false;
}


void UserManager::show_all_user()
{
    if (0 < v_user->size())
    {
        std::cout<<"show all user"<<std::endl;
        for (auto user:*v_user)
        {
            std::cout<<"name:"<<user.name<<std::endl;
            std::cout<<"passwd:"<<user.passwd<<std::endl;
            std::cout<<"administrator:"<<user.administrator<<std::endl;
        }
    }
    else
    {
        std::cout<<"have no user data"<<std::endl;
    }
}

UserManager::~UserManager()
{
    delete v_user;
    v_user = NULL;

    delete userDB;
    userDB = NULL;
}

